import sys
import os
import logging as log

from pid import PidFile
from pid.base import PidFileAlreadyLockedError

basedir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, basedir)
sys.path.insert(0, basedir + '/backup_config')

try:
    from info_config import mongo_backup_dump_base_path
    from info_config import read_prefer
    from info_config import flush_rt
    # from info_config import host_ip

    from backup_utils import yaml_load
    from backup_utils import get_command
    from backup_utils import run_cmd
    from backup_utils import get_file_last_n_line
    from backup_utils import get_host_port_by_string
    from backup_utils import get_current_format_time
    from backup_utils import send_message
    from backup_utils import backup_info_into_dbpt
    from backup_utils import get_last_year_month
    from backup_utils import run_cmd_and_log
    from backup_utils import get_mongo_dump_backup_command
    from backup_utils import make_dir
    # from backup_utils import get_last_month_year_database
    from backup_utils import get_match_data
    from increment_backup import increment_backup
    from mongo_connect import get_connect
    from mongo_connect import get_all_database
    from mongo_connect import get_all_collection
    from mongo_connect import get_master_connect
    from mongo_connect import get_namespace
except Exception as e:
    from info_config import mongo_backup_dump_base_path
    from info_config import read_prefer
    # from info_config import host_ip

    from backup_utils import yaml_load
    from info_config import flush_rt
    from backup_utils import get_command
    from backup_utils import run_cmd
    from backup_utils import get_file_last_n_line
    from backup_utils import get_host_port_by_string
    from backup_utils import get_current_format_time
    from backup_utils import send_message
    from backup_utils import backup_info_into_dbpt
    from backup_utils import run_cmd_and_log
    from backup_utils import make_dir
    from backup_utils import get_mongo_dump_backup_command
    from backup_utils import get_match_data
    from increment_backup import increment_backup

    # from backup_utils import get_last_month_year_database

    from mongo_connect import get_connect
    from mongo_connect import get_all_database
    from mongo_connect import get_all_collection
    from mongo_connect import get_master_connect
    from mongo_connect import get_namespace

    log.exception(str(e))

from backup_utils import get_ip_address

host_ip = get_ip_address()


def get_backup_path(now_format_time, group_id, backup_base_path=mongo_backup_dump_base_path):
    # now_format_time = get_current_format_time()
    if group_id is None:
        raise Exception("group_id is None")
    current_backup_dir = "{backup_base_path}{group_id}/{now_format_time}".format(
        backup_base_path=backup_base_path,
        now_format_time=now_format_time,
        group_id=group_id
    )
    base_backup_dir = "{backup_base_path}{group_id}".format(
        backup_base_path=backup_base_path,
        group_id=group_id
    )
    return current_backup_dir, base_backup_dir


def get_mongodump_log_file(host, port, current_format_time=""):
    log_dir = "{basedir}/mongodump_log/{host}-{port}".format(basedir=basedir, host=host, port=port)
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    run_log_file = "{log_dir}/{current_format_time}-run_result.log".format(log_dir=log_dir,
                                                                           current_format_time=current_format_time)
    return run_log_file


def log_check(host, port, run_log_file):
    if run_log_file is not None:
        last_n_line = get_file_last_n_line(run_log_file, 5)
        for line in last_n_line:
            if "Failed" in line:
                message_to_send = "Mongodb Instance:({host}:{port}) backup failed! " \
                                  "From backup host {host_ip} file_info:{line}".format(host_ip=host_ip, line=line,
                                                                                       host=host,
                                                                                       port=port)
                send_message(message_to_send)
                return 0
        return 1
    else:
        return 0


def run_backup_and_check(host, port, current_format_time, mongo_dump_backup_command, backup_path):
    dump_run_log_file = get_mongodump_log_file(host=host, port=port,
                                               current_format_time=current_format_time)
    run_cmd_and_log(mongo_dump_backup_command, dump_run_log_file)
    is_backup_ok = log_check(host=host, port=port, run_log_file=dump_run_log_file)
    backup_info = {"is_backup_ok": is_backup_ok, "mongodb_host": host, "mongodb_port": port, "remote_host": host_ip,
                   "backup_path": backup_path, "log_file_name": dump_run_log_file}
    backup_info_into_dbpt(backup_info)


def get_cold_db_coll_to_backup(mongodb_connect, db_colls):
    db_coll_to_backup = {}
    if db_colls is None:
        database_list = get_all_database(mongodb_connect)
        last_month_database_year = get_match_data(database_list, year_or_month='year')
        # get_all_collection()
        for database in last_month_database_year:
            mongo_database_instance = get_namespace(mongodb_connect, database)
            mongo_collections = get_all_collection(mongo_database_instance)
            last_month_collection_month = get_match_data(mongo_collections, year_or_month='month')
            db_coll_to_backup.update({database: last_month_collection_month})
        return db_coll_to_backup


def database_backup_main(backup_config, backup_base_path, is_transfer_to_remote):
    # print(backup_config, backup_base_path, is_transfer_to_remote)
    # return
    mongodb_dump_command = get_command(mongodump_path="{basedir}/mongodb/bin".format(basedir=basedir),
                                       mongodump_command_name='mongodump')
    # backup_path_list = []
    current_format_time = get_current_format_time()
    log.debug(backup_config)
    info = backup_config.get('info')

    source_instance_list_string = info.get('source_instance_list')
    source_host, source_port = get_host_port_by_string(source_instance_list_string)

    group_id = info.get('group_id')
    current_backup_dir, base_backup_dir = get_backup_path(now_format_time=current_format_time,
                                                          backup_base_path=backup_base_path,
                                                          group_id=group_id)

    source_mongo_user = info.get('source_mongo_user')
    source_mongo_psw = info.get('source_mongo_psw')
    authentication_database = info.get('authentication_database')
    db_colls = info.get('db_colls')
    is_cold = info.get("is_cold")
    is_increment = info.get('is_increment', 1)  # By default we do the increment backup.
    try:
        pid_path = "%s/full_dump/pid/" % base_backup_dir
        make_dir(pid_path)
        pid_file = "%s/full_dump.pid" % pid_path
        with PidFile(pidname=pid_file):
            if is_cold == 1:
                if authentication_database is None:
                    authentication_database = 'admin'
                mongodb_connect = get_connect(host=source_host, port=source_port, username=source_mongo_user,
                                              password=source_mongo_psw, auth_source=authentication_database)
                mongo_backup_list = get_cold_db_coll_to_backup(mongodb_connect=mongodb_connect, db_colls=db_colls)
                # print(mongo_backup_list)
                for database, collections_list in mongo_backup_list.items():
                    for mgo_collection in collections_list:
                        mongo_dump_backup_command = get_mongo_dump_backup_command(host=source_host, port=source_port,
                                                                                  user=source_mongo_user,
                                                                                  password=source_mongo_psw,
                                                                                  mongodump_command=mongodb_dump_command,
                                                                                  backup_data_path=current_backup_dir,
                                                                                  authentication_database=authentication_database,
                                                                                  database=database,
                                                                                  read_prefer=read_prefer,
                                                                                  collection=mgo_collection)
                        log.debug(mongo_dump_backup_command)
                        run_backup_and_check(host=source_host, port=source_port,
                                             current_format_time=current_format_time,
                                             mongo_dump_backup_command=mongo_dump_backup_command,
                                             backup_path=current_backup_dir)
            else:
                if is_increment == 1:
                    increment_backup(info, backup_path=base_backup_dir, flush_rt=flush_rt)

                if db_colls is not None:
                    for db_coll in db_colls:
                        database = db_coll.get("database")
                        if database is None:
                            log.error("db_colls is not None but database is None")
                        collections = db_coll.get('collections')
                        if authentication_database is None:
                            authentication_database = database
                        if collections is not None:
                            for collection in collections:
                                mongo_dump_backup_command = get_mongo_dump_backup_command(host=source_host,
                                                                                          port=source_port,
                                                                                          user=source_mongo_user,
                                                                                          password=source_mongo_psw,
                                                                                          mongodump_command=mongodb_dump_command,
                                                                                          backup_data_path=current_backup_dir,
                                                                                          authentication_database=authentication_database,
                                                                                          database=database,
                                                                                          read_prefer=read_prefer,
                                                                                          collection=collection)
                                log.debug(mongo_dump_backup_command)
                                run_backup_and_check(host=source_host, port=source_port,
                                                     current_format_time=current_format_time,
                                                     mongo_dump_backup_command=mongo_dump_backup_command,
                                                     backup_path=current_backup_dir)

                        else:
                            mongo_dump_backup_command = get_mongo_dump_backup_command(host=source_host,
                                                                                      port=source_port,
                                                                                      user=source_mongo_user,
                                                                                      password=source_mongo_psw,
                                                                                      mongodump_command=mongodb_dump_command,
                                                                                      authentication_database=authentication_database,
                                                                                      backup_data_path=current_backup_dir,
                                                                                      database=database,
                                                                                      read_prefer=read_prefer
                                                                                      )
                            log.debug(mongo_dump_backup_command)
                            run_backup_and_check(host=source_host, port=source_port,
                                                 current_format_time=current_format_time,
                                                 mongo_dump_backup_command=mongo_dump_backup_command,
                                                 backup_path=current_backup_dir)

                else:
                    if authentication_database is None:
                        authentication_database = 'admin'
                    mongo_dump_backup_command = get_mongo_dump_backup_command(host=source_host, port=source_port,
                                                                              user=source_mongo_user,
                                                                              password=source_mongo_psw,
                                                                              mongodump_command=mongodb_dump_command,
                                                                              authentication_database=authentication_database,
                                                                              backup_data_path=current_backup_dir,
                                                                              read_prefer=read_prefer
                                                                              )

                    log.debug(mongo_dump_backup_command)
                    run_backup_and_check(host=source_host, port=source_port,
                                         current_format_time=current_format_time,
                                         mongo_dump_backup_command=mongo_dump_backup_command,
                                         backup_path=current_backup_dir)
    except PidFileAlreadyLockedError as e:
        log.info("There is already a mongodump backup command running now exit. ")
        return
    if is_transfer_to_remote == 1:
        pass
    # backup_path_list.append(backup_path)
    return current_backup_dir
    # return {"backup_path": backup_path}
